function results =  tobit_g(y,x,ndraw,nomit,prior,start)
% PURPOSE: MCMC sampler for Bayesian Tobit model  
%          y = X B + E, E = N(0,sige*V), 
%          V = diag(v1,v2,...vn), r/vi = ID chi(r)/r, r = Gamma(m,k)
%          B = N(c,T),  sige = gamma(nu,d0)    
%----------------------------------------------------------------
% USAGE: result =  tobit_g(y,x,ndraw,nomit,prior,start)
% where: y = nobs x 1 independent variable vector
%        x = nobs x nvar explanatory variables matrix
%    ndraw = # of draws
%    nomit = # of initial draws omitted for burn-in
%    prior = a structure variable for prior information input
%            prior.beta, prior means for beta,  c above (default=0)
%            priov.bcov, prior beta covariance, T above (default=1e+12)
%            prior.rval, r prior hyperparameter, default=4
%            prior.m,    informative Gamma(m,k) prior on r
%            prior.k,    informative Gamma(m,k) prior on r 
%                        default for above: not used, rval=4 is used
%            prior.nu,   informative Gamma(nu,d0) prior on sige
%            prior.d0    informative Gamma(nu,d0) prior on sige
%                        default for above: nu=0,d0=0 (diffuse prior)
%            prior.trunc = 'left' or 'right' (default = 'left')
%            prior.limit = value for censoring (default = 0)
%    start = (optional) structure containing starting values: 
%            defaults: max likelihood beta, sige, V= ones(n,1)
%            start.b    = beta starting values (nvar x 1)
%            start.sige = sige starting value (1x1)
%            start.V    = V starting values (n x 1)
%---------------------------------------------------------------
% RETURNS: a structure:
%          results.meth  = 'tobit_g'
%          results.bdraw = bhat draws (ndraw-nomit x nvar)
%          results.sdraw = sige draws (ndraw-nomit x 1)
%          results.vmean = mean of vi draws (1 x nobs)
%          results.ymean = mean of y draws (1 x nobs)
%          results.rdraw = r-value draws (ndraw-nomit x 1), if Gamma(m,k) prior
%          results.pmean = b prior means 
%          results.pstd  = b prior std deviations
%          results.m     = prior m-value for r hyperparameter (if input)
%          results.k     = prior k-value for r hyperparameter (if input)
%          results.nu    = prior nu-value for sige prior
%          results.d0    = prior d0-value for sige prior
%          results.r     = value of hyperparameter r (if input)
%          results.nobs  = # of observations
%          results.nobsc = # of censored observations
%          results.nvar  = # of variables
%          results.ndraw = # of draws
%          results.nomit = # of initial draws omitted
%          results.y     = actual observations
%          results.x     = x-matrix
%          results.time  = time taken for sampling
%----------------------------------------------------------------
% NOTE: use either improper prior.rval 
%       or informative Gamma prior.m, prior.k, not both of them
%----------------------------------------------------------------
% References: Siddhartha Chib
%             Bayes Inference in the Tobit censored regression model
%            J. Econometrics Vol. 51, 1992, pp. 79-100.
%----------------------------------------------------------------

% written by:
% James P. LeSage, Dept of Economics
% Texas State University-San Marcos
% 601 University Drive
% San Marcos, TX 78666
% jlesage@spatial-econometrics.com

[n k] = size(x);   

   
if nargin == 6   % user-supplied starting values
    if ~isstruct(start)
    error('tobit_g: must supply starting values in a structure');
     end;
    if ~isstruct(prior)
    error('tobit_g: must supply the prior as a structure variable');
    end;        
sflag = 1; tflag = 0; vflag = 0;
b0 = start.b; sige = start.sig; V = start.V;
    % error checking on starting values input
    [n1 n2] = size(b0); [n3 n4] = size(sige); [n7 n8] = size(V);
    if n1 ~= k
     error('tobit_g: starting beta values are wrong');
    elseif n2 ~= 1
     error('tobit_g: starting beta values are wrong');
    elseif n3 ~= 1
     error('tobit_g: starting sige value is wrong');
    elseif n4 ~= 1
     error('tobit_g: starting sige value is wrong');
    elseif n7 ~= n;
     error('tobit_g: starting V should be nobs x 1');
    elseif n8 ~= 1
     error('tobit_g: starting V should be nobs x 1');
    end;
    
fields = fieldnames(prior);
nf = length(fields);
mm = 0; 
rval = 4;  % rval = 4 is default
nu = 0;    % default diffuse prior for sige
d0 = 0;
c = zeros(k,1);
T = eye(k)*1e+12;
for i=1:nf
    if strcmp(fields{i},'rval')
        rval = prior.rval; 
    elseif strcmp(fields{i},'m')
        mm = prior.m;
        kk = prior.k;
        rval = gamm_rnd(1,1,mm,kk);    % initial value for rval
    elseif strcmp(fields{i},'beta')
        c = prior.beta;
    elseif strcmp(fields{i},'bcov')
        T = prior.bcov;
    elseif strcmp(fields{i},'nu')
        nu = prior.nu;
    elseif strcmp(fields{i},'d0')
        d0 = prior.d0;
    elseif strcmp(fields{i},'trunc');
      if strcmp(prior.trunc,'left');
      tflag = 0;
      else
      tflag = 1;
      end;
    elseif strcmp(fields{i},'limit');
        vflag = prior.limit;            
    end;
end;

elseif  nargin == 5  % probit maximum likelihood starting values

fields = fieldnames(prior);
nf = length(fields);
mm = 0; 
rval = 4;  % rval = 4 is default
nu = 0;    % default diffuse prior for sige
d0 = 0;
c = zeros(k,1);
T = eye(k)*1e+12;
vflag = 0; tflag = 0;
for i=1:nf
    if strcmp(fields{i},'rval')
        rval = prior.rval; 
    elseif strcmp(fields{i},'m')
        mm = prior.m;
        kk = prior.k;
        rval = gamm_rnd(1,1,mm,kk);    % initial value for rval
    elseif strcmp(fields{i},'beta')
        c = prior.beta;
    elseif strcmp(fields{i},'bcov')
        T = prior.bcov;
    elseif strcmp(fields{i},'nu')
        nu = prior.nu;
    elseif strcmp(fields{i},'d0')
        d0 = prior.d0;
    elseif strcmp(fields{i},'trunc');
      if strcmp(prior.trunc,'left');
      tflag = 0;
      else
      tflag = 1;
      end;
    elseif strcmp(fields{i},'limit');
        vflag = prior.limit;           
    end;
end;
    
if tflag == 0    
in.trunc = 'left';
elseif tflag == 1
    in.trunc = 'right';
end;
in.limit = vflag;
resp = tobit(y,x,in);
b0 = resp.beta; 
sige = resp.sige;
V = ones(n,1); in = ones(n,1); % initial value for V  


elseif nargin == 4 % use default prior values
mm = 0; 
rval = 4;  % rval = 4 is default
nu = 0;    % default diffuse prior for sige
d0 = 0;
c = zeros(k,1);
T = eye(k)*1e+12; 
vflag = 0; tflag = 0;
resp = tobit(y,x);
b0 = resp.beta; 
sige = resp.sige;
V = ones(n,1); in = ones(n,1); % initial value for V  

else
error('Wrong # of arguments to tobit_g');
end;

% error checking on prior information inputs
[checkk,junk] = size(c);
if checkk ~= k
error('tobit_g: prior means are wrong');
elseif junk ~= 1
error('tobit_g: prior means are wrong');
end;

[checkk junk] = size(T);
if checkk ~= k
error('tobit_g: prior bcov is wrong');
elseif junk ~= k
error('tobit_g: prior bcov is wrong');
end;


Q = inv(T);
Qpc = Q*c;

bsave = zeros(ndraw-nomit,k);    % allocate storage for results
ymean = zeros(1,n); 
rsave = zeros(ndraw-nomit,1);
vmean = zeros(1,n);
ssave = zeros(ndraw-nomit,1);

yin = y;          % save original y-values

% find # of censored observations
if tflag == 1
   results.nobsc = length(find(y >= vflag));
else
   results.nobsc = length(find(y <= vflag));
end;

ind_left = find(yin <= vflag); 
ileft = ones(length(ind_left),1);    
ind_right = find(yin >= vflag);
iright = ones(length(ind_right),1);

hwait = waitbar(0,'MCMC sampling ...');
t0 = clock;                  
%  Start the sampling
for iter=1:ndraw;

          % update b ;
          xstar = matmul(x,sqrt(V));
          ystar = y.*sqrt(V);
          xpxi = inv(xstar'*xstar + sige*Q);
          b = xpxi*(xstar'*ystar + sige*Qpc);
          % draw MV normal with mean(b), var(b)
          beta = norm_rnd(sige*xpxi) + b;
         
          % update sige 
          nu1 = n + nu; 
          e = ystar - xstar*beta;
          d1 = d0 + e'*e;
          chi = chis_rnd(1,nu1);
          sige =d1/chi;
          
          % update V
          e = y - x*beta;
          chiv = chis_rnd(n,rval+1);   
          vi = ((e.*e./sige) + in*rval)./chiv;
          V = in./vi;  

          % update r
          if mm ~= 0
          rval = gamm_rnd(1,1,mm,kk);  % update rval
          end;
                  
         % simulate y from truncated normal 
         aa = x*b;
         if tflag == 0 % left censoring
            % simulate from truncated normal at the right
           y(ind_left,1) = normrt_rnd(aa(ind_left,1),sige*ileft,vflag*ileft);
         else % right censoring
            % simulate from truncated normal at the left
           y(ind_right,1) = normlt_rnd(aa(ind_right,1),sige*iright,vflag*iright);
         end;

if iter > nomit; % save draws
vmean = vmean + vi';            
ssave(iter-nomit,1) = sige;
bsave(iter-nomit,:) = beta';
ymean = ymean + y';
    if mm~= 0
        rsave(i-nomit,1) = rval;
    end;
end; % end of if
          
waitbar(iter/ndraw);

end;% end of for iter=1:ndraw
gtime = etime(clock,t0);
close(hwait);

vmean = vmean/(ndraw-nomit);
ymean = ymean/(ndraw-nomit);

results.meth  = 'tobit_g';
results.bdraw = bsave;
results.sdraw = ssave;
results.vmean = vmean;
results.ymean = ymean;
results.pmean = c;
results.pstd  = sqrt(diag(T));
if mm~= 0
results.rdraw = rsave;
results.m     = mm;
results.k     = kk;
else
results.r     = rval;
results.rdraw = rsave;
end;
results.nobs  = n;
results.nvar  = k;
results.ndraw = ndraw;
results.nomit = nomit;
results.time = gtime;
results.y = yin;
results.x = x;
results.nu = nu;
results.d0 = d0;
results.pflag = 'plevel';